# -*- coding: utf-8 -*-
from __future__ import with_statement

import os
import urllib
import mimetypes
from django.conf import settings
from django.utils.encoding import smart_str, smart_unicode
from django.utils.translation import ugettext as _

from mercurial import hg, ui, revlog

import utils

class Lock(object):
    def __init__(self, repos):
        self._repos = repos
        self._lock = repos.wlock()

    def __enter__(self):
        self._lock.lock()

    def __exit__(self, exc_type, exc_value, traceback):
        self._lock.release()

class Document(object):
    def __init__(self, wikiname, content=None):
        self._wikiname = smart_unicode(wikiname)
        self._filename = urllib.quote(smart_str(wikiname))
        self._repos = hg.repository(ui.ui(), settings.WIKI_REPOSITORY)
        hg.update(self._repos, None)

    filename = property(lambda x: x._filename)
    word = property(lambda x: x._wikiname)

    def __unicode__(self):
        return self._wikiname

    def get_parent_dir(self):
        return os.path.dirname(self._filename)
    parent_dir = property(get_parent_dir)

    def get_mimetype(self):
        mimetype, encoding = mimetypes.guess_type(self._filename)
        if not mimetype:
            return 'application/octet-stream'
        else:
            return mimetype
    mimetype = property(get_mimetype)

    def write(self, data, username=None, description=None):
        filename = self._filename
        username = username or 'anonymous'
        description = description or _('Updated by %s') % username

        fullpath = os.path.join(settings.WIKI_REPOSITORY, filename)
        if not os.path.isdir(os.path.dirname(fullpath)):
            os.makedirs(os.path.dirname(fullpath))

        with Lock(self._repos):
            with file(fullpath, 'wb') as fp:
                fp.write(data)
            self._repos.add([filename])
            self._repos.commit([filename], description, username, force_editor=False)

    def read(self, revision=None):
        repos = self._repos
        ctx = repos.changectx()
        head = ctx.rev()
        try:
            fctx = repos.filectx(self._filename, head)
            if revision is None:
                return fctx.data()

            maxchange = fctx.filelog().count() - 1
            revision = maxchange + revision
            r = fctx.filectx(revision)
            return r.data()
        except revlog.LookupError:
            return None

    def get_data(self):
        try:
            return self._data
        except AttributeError:
            self._data = self.read()
            return self._data
    data = property(get_data)

    def get_content(self):
        return unicode(self.data, settings.DEFAULT_CHARSET)
    content = property(get_content)

    def remove(self, username=None, description=None):
        username = username or 'anonymous'
        desciption = _('Removed by %s') % username
        with Lock(self._repos):
            self._repos.remove([self._filename], unlink=True)
            self._repos.commit([self._filename], desciption, username, force_editor=False)

    def is_binary(self):
        return utils.is_binary(self.data)

    def is_image(self):
        mimetype, encoding = mimetypes.guess_type(self._filename)
        if mimetype and mimetype.startswith('image'):
            return utils.is_image(self.data)
        return False

    def get_absolute_url(self):
        return '/%s' % self._filename
